package com.hqd.ch03.v31.tx.transaction.support;

import com.hqd.ch03.v31.tx.transaction.SavepointManager;
import com.hqd.ch03.v31.tx.transaction.TransactionStatus;

public abstract class AbstractTransactionStatus implements TransactionStatus {
    private boolean rollbackOnly = false;

    private boolean completed = false;

    private Object savepoint;


    @Override
    public void setRollbackOnly() {
        this.rollbackOnly = true;
    }

    @Override
    public boolean isRollbackOnly() {
        return (isLocalRollbackOnly() || isGlobalRollbackOnly());
    }

    public boolean isLocalRollbackOnly() {
        return this.rollbackOnly;
    }

    public boolean isGlobalRollbackOnly() {
        return false;
    }

    public void setCompleted() {
        this.completed = true;
    }

    @Override
    public boolean isCompleted() {
        return this.completed;
    }


    @Override
    public boolean hasSavepoint() {
        return (this.savepoint != null);
    }

    protected Object getSavepoint() {
        return this.savepoint;
    }

    protected void setSavepoint(Object savepoint) {
        this.savepoint = savepoint;
    }

    public void createAndHoldSavepoint() {
        setSavepoint(getSavepointManager().createSavepoint());
    }

    public void rollbackToHeldSavepoint() {
        Object savepoint = getSavepoint();
        if (savepoint == null) {
            throw new RuntimeException(
                    "Cannot roll back to savepoint - no savepoint associated with current transaction");
        }
        getSavepointManager().rollbackToSavepoint(savepoint);
        getSavepointManager().releaseSavepoint(savepoint);
        setSavepoint(null);
    }

    public void releaseHeldSavepoint() {
        Object savepoint = getSavepoint();
        if (savepoint == null) {
            throw new RuntimeException(
                    "Cannot release savepoint - no savepoint associated with current transaction");
        }
        getSavepointManager().releaseSavepoint(savepoint);
        setSavepoint(null);
    }

    @Override
    public Object createSavepoint() {
        return getSavepointManager().createSavepoint();
    }

    @Override
    public void rollbackToSavepoint(Object savepoint) {
        getSavepointManager().rollbackToSavepoint(savepoint);
    }

    @Override
    public void releaseSavepoint(Object savepoint) {
        getSavepointManager().releaseSavepoint(savepoint);
    }

    protected SavepointManager getSavepointManager() {
        throw new RuntimeException("This transaction does not support savepoints");
    }

    @Override
    public void flush() {
    }
}
